package com.module.home.ui.healthDataDetails

import androidx.core.content.ContextCompat
import androidx.lifecycle.LiveData
import com.common.app.utls.TimeUtils
import com.common.app.utls.TimeUtils.getTimeDateLong
import com.common.app.utls.TimeUtils.getWeek
import com.common.app.utls.TimeUtils.getYearAndMonth
import com.common.app.utls.TimeUtils.getYearMonthDay
import com.common.base.app.extras.setText
import com.common.base.app.extras.setViIn
import com.common.base.app.fragment.BaseVMFragment
import com.common.base.utils.JsonUtils
import com.common.base.utils.LogUtils
import com.common.base.utils.ViewUtils.getColor
import com.module.ble.data.bean.CusChartData
import com.module.ble.data.bean.CusUnifyData
import com.module.ble.db.table.UserHeartRate
import com.module.ble.utils.CommonCusHealthType
import com.module.ble.utils.BleOtherUtil.convertBloodOxygen
import com.module.ble.utils.BleOtherUtil.convertToChartData
import com.module.ble.utils.BleOtherUtil.createWeekTemplateData
import com.module.ble.utils.BleOtherUtil.loadMonthData
import com.module.ble.utils.CycleType
import com.module.ble.widget.BloodOxygenChart
import com.module.ble.widget.BrokenLineChart
import com.module.ble.widget.FloatMonthChart
import com.module.ble.widget.FloatWeekChart
import com.module.home.R
import com.module.home.databinding.HomeFragmentHeartDayDataDetailsBinding
import com.scwang.smart.refresh.footer.ClassicsFooter
import com.scwang.smart.refresh.header.ClassicsHeader
import com.scwang.smart.refresh.layout.api.RefreshLayout
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener
import java.util.Calendar

/**
 *
 * 作者：sosou
 *
 * 版本：1.0
 *
 * 创建日期：2024/11/18
 *
 * 描述：
 *
 * 修订历史：
 *
 */
class HeartDetailsDayFragment :
    BaseVMFragment<HomeFragmentHeartDayDataDetailsBinding, HealthDataDetailsViewModel>() {

    private val brokenLineChart by lazy { BrokenLineChart(requireActivity()) }
    private val bloodOxygenChart by lazy { BloodOxygenChart(requireActivity()) }
    private val floatWeekChart by lazy { FloatWeekChart(requireActivity()) }
    private val floatMonthChart by lazy { FloatMonthChart(requireActivity()) }

    private val classicsFooter by lazy { ClassicsFooter(requireActivity()) }

    companion object {
        fun newInstance(
            mType: Int = CommonCusHealthType.HEARTRATE.value,
            mCycle: CycleType = CycleType.DAY
        ): HeartDetailsDayFragment {
            val fragment = HeartDetailsDayFragment()
            fragment.mType = mType
            fragment.mCycle = mCycle
            return fragment
        }
    }

    private var mType: Int = CommonCusHealthType.HEARTRATE.value
    private var mCycle: CycleType = CycleType.DAY//周期：

//    override fun getPlaceholderView() = mViewBinding.placeView

    override fun getViewModel() = HealthDataDetailsViewModel::class.java

    override fun getViewBinding() = HomeFragmentHeartDayDataDetailsBinding.inflate(layoutInflater)

    override fun initViews() {
        super.initViews()

        //上下拉刷新
        getRefreshFooter()?.let { mViewBinding.pdView.setRefreshFooter(it) }
        mViewBinding.pdView.setRefreshHeader(
            ClassicsHeader(requireActivity()).setAccentColor(
                ContextCompat.getColor(requireActivity(), R.color.text_content_week)
            )
        )
        classicsFooter.setAccentColor(
            ContextCompat.getColor(
                requireActivity(),
                R.color.color_999999
            )
        )
        mViewBinding.pdView.setRefreshFooter(classicsFooter)

        mViewBinding.kvValue1.setKey("${getString(R.string.common_highest_unit)}${getTypeHint()}")
        mViewBinding.kvValue2.setKey("${getString(R.string.common_average_unit)}${getTypeHint()}")
        mViewBinding.kvValue3.setKey("${getString(R.string.common_minimum_unit)}${getTypeHint()}")

        mViewModel.initCycleData(mType, mCycle)

        when (mCycle) {
            CycleType.WEEK -> {
                mViewBinding.totalHeart.addView(floatWeekChart)
                setupWeeklyDataObservation()
            }

            CycleType.MONTH -> {
                mViewBinding.totalHeart.addView(floatMonthChart)
                setupMonthlyDataObservation()
            }

            else -> {
                setupDailyDataObservation()
            }
        }
    }

    override fun lazyInitData() {
        super.lazyInitData()
        val date = getYearMonthDay(getTimeDateLong())
        setText(mViewBinding.tvDate, "$date${getWeek(date)}")
    }


    override fun initEvents() {
        super.initEvents()
        setErrorRetryListener {
            lazyInitData()
        }

        mViewBinding.pdView.setOnRefreshLoadMoreListener(object : OnRefreshLoadMoreListener {
            override fun onRefresh(refreshLayout: RefreshLayout) {
                mViewModel.refreshDBAllData()
                refreshLayout.layout.postDelayed({
                    finishPdView()
                }, 2000)
            }

            override fun onLoadMore(refreshLayout: RefreshLayout) {
                mViewBinding.pdView.setEnableLoadMoreWhenContentNotFull(false)
                mViewBinding.pdView.finishLoadMoreWithNoMoreData()
            }
        })

//        mViewContentBinding.tvLoginOut.setOnClickListener(onClick = this)
    }

    private fun finishPdView() {
        mViewBinding.pdView.finishRefresh()
        mViewBinding.pdView.finishLoadMore()
    }

    fun getTypeTimeHint(time: Long) = when(mCycle){
        CycleType.DAY-> "时间: ${TimeUtils.getHourAndYear(time)}"
        CycleType.WEEK, CycleType.MONTH-> "时间: ${getYearMonthDay(time)}"
        else->""
    }

    fun getTypeHint() = when(mType){
        CommonCusHealthType.HEARTRATE.value-> getString(R.string.common_heart_rate_hint)
        CommonCusHealthType.BLOODOXYGEN.value-> getString(R.string.common_blood_oxygen_hint)
        CommonCusHealthType.BODYTEMP.value-> getString(R.string.common_body_temp_hint)
        else->""
    }

    /**
     * 计算心率数据的统计信息（最高值、平均值、最低值）
     * @param dataList 心率数据列表
     * @return 包含最高值、平均值、最低值的统计对象
     */
    fun calculateHeartRateStats(dataList: List<CusUnifyData>) {
        if (dataList.isEmpty()) return

        val maxValue = dataList.maxOf { it.value.toFloat() }
        val minValue = dataList.minOf { it.value.toFloat() }
        val avgValue = dataList.map { it.value.toFloat() }.average().toFloat()

        mViewBinding.kvValue1.setValue(maxValue.toInt().toString())
        mViewBinding.kvValue2.setValue(avgValue.toInt().toString())
        mViewBinding.kvValue3.setValue(minValue.toInt().toString())
    }

    fun setHeartRateDayData(dataList: List<UserHeartRate>) {

        val convertData = convertToChartData(dataList)
        val strTemp = JsonUtils.toJson(convertData)
        // 更新 UI
        brokenLineChart.apply {
            setShowZeroLine(false)
            setPaintDefaultColor(getColor(R.color.c_f97975))
            setShowZeroLineColor(getColor(R.color.c_f97975))
            setShowSlider(true)
            setShowYAxisLabel(true)     // 显示或隐藏右边的文字
            setBusinessType(mType)
            setValue(convertData.first)
            setOnDaySelectListener { index, heartRate ->
                setViIn(mViewBinding.tvTime, (index > 0))
                setText(
                    mViewBinding.tvTime,
                    getTypeTimeHint(index)
                )
                setText(
                    mViewBinding.tvValue,
                    if (heartRate > -1) "${getTypeHint()}: $heartRate" else getString(R.string.base_no_data3)
                )
            }
        }
    }

    fun setWeekData(dataList: List<CusUnifyData>) {
        LogUtils.e("dataList:", JsonUtils.toJson(dataList))
        val chartData = createWeekTemplateData()

        // 按照周几将心率数据分组(0-6表示周一到周日)
        val groupedByDay = dataList.groupBy { data ->
            val calendar = Calendar.getInstance()
            calendar.timeInMillis = data.mTime
            when (calendar.get(Calendar.DAY_OF_WEEK)) {
                Calendar.MONDAY -> 0
                Calendar.TUESDAY -> 1
                Calendar.WEDNESDAY -> 2
                Calendar.THURSDAY -> 3
                Calendar.FRIDAY -> 4
                Calendar.SATURDAY -> 5
                Calendar.SUNDAY -> 6
                else -> -1  //理论上不会出现这种情况
            }
        }

        // 更新每天的最小和最大心率值
        groupedByDay.forEach { (dayIndex, dayData) ->
            if (dayIndex in 0..6) {// 确保索引有效
                val minHeartRate = dayData.minOfOrNull { it.value.toFloat() } ?: 0f
                val maxHeartRate = dayData.maxOfOrNull { it.value.toFloat() } ?: 0f
                chartData[dayIndex].minValue = minHeartRate  // 最小心率
                chartData[dayIndex].mValue = maxHeartRate    // 最大心率
            }
        }

        // 1. 基本设置，更新图表
        floatWeekChart.apply {
            setShowSlider(true) // 显示底部滑块
            setShowZeroLine(true) // 显示0刻度线
            setBarColor(
                when (mType) {
                    CommonCusHealthType.BLOODOXYGEN.value -> getColor(R.color.c_6acd7a_30)
                    CommonCusHealthType.BODYTEMP.value -> getColor(R.color.c_61d1ba_30)
                    else -> getColor(R.color.c_f97975_30)
                }, when (mType) {
                    CommonCusHealthType.BLOODOXYGEN.value -> getColor(R.color.c_6acd7a)
                    CommonCusHealthType.BODYTEMP.value -> getColor(R.color.c_61d1ba)
                    else -> getColor(R.color.c_f97975)
                }
            )
            setShowZeroLineColor(
                when (mType) {
                    CommonCusHealthType.BLOODOXYGEN.value -> getColor(R.color.c_6acd7a)
                    CommonCusHealthType.BODYTEMP.value -> getColor(R.color.c_61d1ba)
                    else -> getColor(R.color.c_f97975)
                }
            )
            setShowBarBackground(false) // 显示背景柱子颜色
            setShowYAxisLabel(true)     // 显示或隐藏右边的文字false
            setBusinessType(mType)
            setValue(chartData, defaultPosition = 2)

            setOnDaySelectListener { index, max: Float, min: Float ->
                setViIn(mViewBinding.tvTime, (index > 0))
                setText(mViewBinding.tvTime, getTypeTimeHint(index))
                setText(mViewBinding.tvValue, if (max > 0) "${getTypeHint()}: $max-$min" else getString(R.string.base_no_data3))
            }
        }
    }

    fun setMonthData(dataList : List<CusUnifyData>) {
        val timeTamp = getYearAndMonth(getTimeDateLong())
        val monthData = loadMonthData(timeTamp.first, timeTamp.second)

        // 按日期分组数据
        val groupedByDay = dataList.groupBy { data ->
            val calendar = Calendar.getInstance()
            calendar.timeInMillis = data.mTime
            val dataYear = calendar.get(Calendar.YEAR)
            val dataMonth = calendar.get(Calendar.MONTH) + 1 // Calendar.MONTH是0-11
            val dataDay = calendar.get(Calendar.DAY_OF_MONTH)

            // 只处理匹配指定年月的数据
            if (dataYear == timeTamp.first && dataMonth == timeTamp.second) {
                dataDay // 返回日期（1-31）
            } else {
                -1 // 表示不在当前月份
            }
        }

        // 更新每天的最小和最大心率值
        groupedByDay.forEach { (day, dayData) ->
            if (day in 1..monthData.size) { // 确保日期有效
                val dayIndex = day - 1 // 列表索引从0开始，日期从1开始
                val minHeartRate = dayData.minOfOrNull { it.value.toFloat() } ?: 0f
                val maxHeartRate = dayData.maxOfOrNull { it.value.toFloat() } ?: 0f

                monthData[dayIndex].minValue = minHeartRate // 最小心率
                monthData[dayIndex].mValue = maxHeartRate   // 最大心率
            }
        }

        val temp = JsonUtils.toJson(monthData)
        // 1. 基本设置，更新图表
        floatMonthChart.apply {
            setShowSlider(true) // 显示底部滑块
            setShowZeroLine(true) // 显示0刻度线
            setBarColor(
                when (mType) {
                    CommonCusHealthType.BLOODOXYGEN.value -> getColor(R.color.c_6acd7a_30)
                    CommonCusHealthType.BODYTEMP.value -> getColor(R.color.c_61d1ba_30)
                    else -> getColor(R.color.c_f97975_30)
                }, when (mType) {
                    CommonCusHealthType.BLOODOXYGEN.value -> getColor(R.color.c_6acd7a)
                    CommonCusHealthType.BODYTEMP.value -> getColor(R.color.c_61d1ba)
                    else -> getColor(R.color.c_f97975)
                }
            )
            setShowZeroLineColor(
                when (mType) {
                    CommonCusHealthType.BLOODOXYGEN.value -> getColor(R.color.c_6acd7a)
                    CommonCusHealthType.BODYTEMP.value -> getColor(R.color.c_61d1ba)
                    else -> getColor(R.color.c_f97975)
                }
            )
            setShowBarBackground(false) // 显示背景柱子颜色
            setShowYAxisLabel(true)     // 显示或隐藏右边的文字false
            setBusinessType(mType)
            setValue(monthData)

            setOnDaySelectListener { index, max: Float, min: Float ->
                setViIn(mViewBinding.tvTime, (index > 0))
                setText(mViewBinding.tvTime, getTypeTimeHint(index))
                setText(mViewBinding.tvValue, if (max > 0) "${getTypeHint()}: $max-$min" else getString(R.string.base_no_data3))
            }
        }
    }

    // 通用的数据观察函数
    private fun <T> observeData(
        liveData: LiveData<List<T>>?,
        dataProcessor: (List<T>) -> Unit,
        statsCalculator: (List<T>) -> Unit
    ) {
        liveData?.observe(this) { data ->
            dataProcessor(data)
            statsCalculator(data)
        }
    }

    //辅助函数，处理周数据观察
    private fun setupWeeklyDataObservation() {
        when (mType) {
            CommonCusHealthType.BLOODOXYGEN.value -> observeData(
                mViewModel.allBloodOxygens,
                ::setWeekData,
                ::calculateHeartRateStats
            )
            CommonCusHealthType.BODYTEMP.value -> observeData(
                mViewModel.allUserBodyTemperatures,
                ::setWeekData,
                ::calculateHeartRateStats
            )
            else -> observeData(
                mViewModel.allHeartRates,
                ::setWeekData,
                ::calculateHeartRateStats
            )
        }
    }

    // 辅助函数，处理月数据观察
    private fun setupMonthlyDataObservation() {
        when (mType) {
            CommonCusHealthType.BLOODOXYGEN.value -> observeData(
                mViewModel.allBloodOxygens,
                ::setMonthData,
                ::calculateHeartRateStats
            )

            CommonCusHealthType.BODYTEMP.value -> observeData(
                mViewModel.allUserBodyTemperatures,
                ::setMonthData,
                ::calculateHeartRateStats
            )

            else -> observeData(
                mViewModel.allHeartRates,
                ::setMonthData,
                ::calculateHeartRateStats
            )
        }
    }

    // 血氧图表配置
    private fun configureBloodOxygenChart(convertData: Pair<List<CusChartData>, *>) {
        bloodOxygenChart.apply {
            setShowSlider(true)
            setShowZeroLineColor(getColor(R.color.c_6acd7a))
            setShowZeroLine(false)
            setShowBarBackground(false)
            setShowYAxisLabel(true)
            setValue(convertData.first)
            setOnDaySelectListener { index, heartRate ->
                setViIn(mViewBinding.tvTime, (index > 0))
                setText(
                    mViewBinding.tvTime,
                    getTypeTimeHint(index)
                )
                setText(
                    mViewBinding.tvValue,
                    if (heartRate > -1) "${getTypeHint()}: $heartRate" else getString(R.string.base_no_data3)
                )
            }
        }
    }

    // 体温图表配置
    private fun configureBodyTempChart(convertData: Pair<List<CusChartData>, *>) {
        brokenLineChart.apply {
            setPaintDefaultColor(getColor(R.color.c_61d1ba))
            setShowZeroLineColor(getColor(R.color.c_61d1ba))
            setShowZeroLine(false)
            setShowSlider(true)
            setShowYAxisLabel(true)
            setBusinessType(mType)
            setValue(convertData.first)
            setOnDaySelectListener { index, heartRate ->
                setText(
                    mViewBinding.tvTime,
                    getTypeTimeHint(index)
                )
                setText(
                    mViewBinding.tvValue,
                    if (heartRate > -1) "${getTypeHint()}: $heartRate" else getString(R.string.base_no_data3)
                )
            }
        }
    }

    // 辅助函数，处理日数据观察
    private fun setupDailyDataObservation() {
        when (mType) {
            CommonCusHealthType.BLOODOXYGEN.value -> {
                mViewModel.allBloodOxygens?.observe(this) { bloodOxygens ->
                    val convertData = convertBloodOxygen(bloodOxygens)
                    configureBloodOxygenChart(convertData)
                    calculateHeartRateStats(bloodOxygens)
                }
                mViewBinding.totalHeart.addView(bloodOxygenChart)
            }

            CommonCusHealthType.BODYTEMP.value -> {
                mViewModel.allUserBodyTemperatures?.observe(this) { bodyTemps ->
                    val convertData = convertToChartData(bodyTemps)
                    configureBodyTempChart(convertData)
                    calculateHeartRateStats(bodyTemps)
                }
                mViewBinding.totalHeart.addView(brokenLineChart)
            }

            else -> {
                mViewModel.allHeartRates?.observe(this) { heartRates ->
                    setHeartRateDayData(heartRates)
                    calculateHeartRateStats(heartRates)
                }
                mViewBinding.totalHeart.addView(brokenLineChart)
            }
        }
    }
}